/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: skahl $
 * $Revision: 1.14 $
 * $Date: 2007/08/31 08:18:27 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.adapters.contenthandler;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import au.edu.educationau.opensource.dsm.adapters.SearchAdapterProperties;
import au.edu.educationau.opensource.dsm.obj.ResultCategory;
import au.edu.educationau.opensource.dsm.obj.ResultMetadata;
import au.edu.educationau.opensource.dsm.obj.SearchResult;
import au.edu.educationau.opensource.dsm.worker.ResultSetUnifier;

public class EDNAContentHandler extends DefaultHandler {
	private SearchResult result = new SearchResult();
	private ResultCategory cat = new ResultCategory();
	private ArrayList results = new ArrayList();
	private ArrayList categories = new ArrayList(5);
	private ArrayList metadata = new ArrayList(5);

	private StringBuffer titleBuffer = new StringBuffer();
	private StringBuffer titleAlternativeBuffer = new StringBuffer();
	private StringBuffer descriptionBuffer = new StringBuffer();
	private StringBuffer identifierBuffer = new StringBuffer();
	private StringBuffer previewBuffer = new StringBuffer();
	private StringBuffer downloadBuffer = new StringBuffer();
	private StringBuffer categoryNameBuffer = new StringBuffer();
	private StringBuffer dateBuffer = new StringBuffer();

	private short total = 0;
	private short found = 0;
	private short start = 0;
	private short count = 0;

	private String currentElement = "";
	private String previousElement = "";
	private SearchAdapterProperties props = new SearchAdapterProperties();

	private boolean useLink = false;

	/***/
	public short getFound() {
		return found;
	}

	/***/
	public short getTotal() {
		return total;
	}

	/***/
	public short getStart() {
		return start;
	}

	/***/
	public short getCount() {
		return count;
	}

	/***/
	public ArrayList getResults() {
		return results;
	}

	/**
	 * @param props
	 */
	public void setSearchAdapterProperties(SearchAdapterProperties props) {
		this.props = props;
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void characters(char[] ch, int ch_start, int ch_length) throws SAXException {
		String val = String.copyValueOf(ch, ch_start, ch_length);

		// SUMMARY
		if (currentElement.equals("start")) {
			try {
				this.start = Short.parseShort(val);
			} catch (NumberFormatException oe) {
			}
		} else if (currentElement.equals("total")) {
			try {
				this.total = Short.parseShort(val);
			} catch (NumberFormatException oe) {
			}
		} else if (currentElement.equals("found")) {
			try {
				this.found = Short.parseShort(val);
			} catch (NumberFormatException oe) {
			}
		} else if (currentElement.equals("count")) {
			try {
				this.count = Short.parseShort(val);
			} catch (NumberFormatException oe) {
			}
		}
		// ITEMS
		else if (currentElement.equals("identifier")) {
			if (!useLink) {
				identifierBuffer.append(val);
			}
		} else if (currentElement.equals("link")) {
			if (useLink) {
				identifierBuffer.append(val);
			}
		} else if (currentElement.equals("preview")) {
			previewBuffer.append(val);
		} else if (currentElement.equals("download")) {
			downloadBuffer.append(val);
		} else if (currentElement.equals("score") || currentElement.equals("relevance")) {
			float relevance = 0f;
			try {
				relevance = Float.parseFloat(val);
			} catch (NumberFormatException oe) {
			}
			this.result.setRelevance(ResultSetUnifier.normaliseRelevance(relevance, props.getRelevanceMultiplier(), props.getRelevanceOffset()));
		} else if (currentElement.equals("title")) {
			titleBuffer.append(val);
		} else if (currentElement.equals("title_alternative")) {
			titleAlternativeBuffer.append(val);
		} else if (currentElement.equals("itemcode")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("itemcode", val));
				this.result.setIdentifier("edna:" + val);
			}
		} else if (currentElement.equals("availability")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("availability", val));
			}
		} else if (currentElement.equals("format")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("format", val));
			}
		} else if (currentElement.equals("collection")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("collection", val));
			}
		} else if (currentElement.equals("edna.collection")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("edna.collection", val));
			}
		} else if (currentElement.equals("licencetype")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("licencetype", val));
			}
		} else if (currentElement.equals("ev_date_start")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("ev_date_start", val));
			}
		} else if (currentElement.equals("ev_mode")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("ev_mode", val));
			}
		} else if (currentElement.equals("ev_location_region")) {
			if (val.length() > 0) {
				this.metadata.add(new ResultMetadata("ev_location_region", val));
			}
		} else if (currentElement.equals("description")) {
			descriptionBuffer.append(val);
		}
		// CATEGORIES
		else if (currentElement.equals("code")) {
			this.cat.setCode(val);
		} else if (currentElement.equals("name")) {
			categoryNameBuffer.append(val);
		} else if (currentElement.equals("path")) {
			this.cat.addPath(val);
		} else if (currentElement.equals("alias")) {
			this.cat.setAlias(val);
		} else if (currentElement.equals("date")) {
			dateBuffer.append(val);
		} else if (currentElement.equals("")) {
			if (previousElement.equals("description")) {
				descriptionBuffer.append(val);
			} else if (previousElement.equals("title")) {
				titleBuffer.append(val);
			} else if (previousElement.equals("title_alternative")) {
				titleAlternativeBuffer.append(val);
			} else if (previousElement.equals("identifier")) {
				if (!useLink) {
					identifierBuffer.append(val);
				}
			} else if (previousElement.equals("link")) {
				if (useLink) {
					identifierBuffer.append(val);
				}
			} else if (previousElement.equals("preview")) {
				previewBuffer.append(val);
			} else if (previousElement.equals("download")) {
				downloadBuffer.append(val);
			} else if (previousElement.equals("name")) {
				categoryNameBuffer.append(val);
			} else if (previousElement.equals("date")) {
				dateBuffer.append(val);
			}
		}
		if (!currentElement.equals("")) {
			previousElement = currentElement;
		}
		currentElement = "";
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void ignorableWhitespace(char[] ch, int ch_start, int ch_length) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @exception SAXException
	 */
	public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) throws SAXException {
		if (localName.equals("item")) {
			result.setDescription(descriptionBuffer.toString().trim());
			result.setLink(identifierBuffer.toString().trim());
			result.setPreview(previewBuffer.toString().trim());
			result.setDownload(downloadBuffer.toString().trim());
			result.setTitle(titleBuffer.toString().trim());
			result.setDate(dateBuffer.toString().trim());
			result.setSource(props.getAdapterCode());
			result.setCollectionName(props.getDisplayTitle());
			if (titleAlternativeBuffer.length() > 0) {
				metadata.add(new ResultMetadata("title_alternative", titleAlternativeBuffer.toString().trim()));
			}
			metadata.trimToSize();
			ResultMetadata[] metadataArray = new ResultMetadata[metadata.size()];
			result.setResultMetadata((ResultMetadata[]) metadata.toArray(metadataArray));
			results.add(result);
		} else if (localName.equals("category")) {
			this.cat.setName(categoryNameBuffer.toString().trim());
			categories.add(cat);
		} else if (localName.equals("category_item_link")) {
			categories.trimToSize();
			ResultCategory[] catArray = new ResultCategory[categories.size()];
			result.setResultCategories((ResultCategory[]) categories.toArray(catArray));
		}

	}

	/**
	 * @param target
	 * @param data
	 * @exception SAXException
	 */
	public void processingInstruction(String target, String data) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attr
	 * @exception SAXException
	 */
	public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes attr) throws SAXException {
		this.currentElement = localName;
		if (localName.equals("item")) {
			result = new SearchResult();
			titleBuffer = new StringBuffer();
			titleAlternativeBuffer = new StringBuffer();
			descriptionBuffer = new StringBuffer();
			identifierBuffer = new StringBuffer();
			previewBuffer = new StringBuffer();
			downloadBuffer = new StringBuffer();
			dateBuffer = new StringBuffer();
			metadata = new ArrayList(5);
		} else if (localName.equals("category")) {
			cat = new ResultCategory();
			categoryNameBuffer = new StringBuffer();
		} else if (localName.equals("category_item_link")) {
			cat = new ResultCategory();
			categories = new ArrayList(5);
		} else if (localName.equals("link")) {
			useLink = true;
		}
	}

}
